package com.kebaijia.morenio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/**
 * @author luoy
 * @date 2018/7/24 0024 上午 9:05
 * @Description: ${todo}
 */
public class NioServer {
    public static void main(String[] args) throws Exception {
        //开启服务器端通道
        ServerSocketChannel schannel = ServerSocketChannel.open();

        //绑定端口
        schannel.bind(new InetSocketAddress(9000));

        //设置非阻塞
        schannel.configureBlocking(false);

        //开启选择器
        Selector selector = Selector.open();

        /**
         * 把channel注册到选择器
         * 参数2，告诉选择器对那些事件感兴趣,SelectionKey.OP_ACCEPT表示对客户端连接感兴趣
         */
        schannel.register(selector,SelectionKey.OP_ACCEPT);

        while (true){
            //这个方法会阻塞，当所有schannel都没事的话阻塞，当有一个schannel发了事件，他就会离开阻塞状态
            selector.select();
            //SelectionKey是schannel和selecor建立注册关系的契约，每个注册的schannel都有一个SelectionKey
            //SelectionKey相当于警报器
            Set<SelectionKey> keys = selector.selectedKeys();

            //遍历keys就可以知道谁有事
            Iterator<SelectionKey> it = keys.iterator();

            /**
             * 迭代器遍历，删除处理了之后的schannel
             */
            while (it.hasNext()){
                SelectionKey key = it.next();
                it.remove();//先从集合里面删除他

                //说明他是客户端连接的事件
                if(key.isAcceptable()){
                    //拿到客户端连接所对应的channel
                    SocketChannel channel = schannel.accept();
                    //设置非阻塞
                    channel.configureBlocking(false);
                    //感兴趣事件，SelectionKey.OP_READ代表准备好读取数据
                    channel.register(selector,SelectionKey.OP_READ);
                }
                //当有客户端发送数据时，服务器准备去读数据
                if(key.isReadable()){
                    //准备一个空buffer
                    ByteBuffer buffer = ByteBuffer.allocate(20);
                    //得到有事的channel
                    SocketChannel channel = (SocketChannel) key.channel();
                    //一个一个字节读进buffer
                    channel.read(buffer);
                    //从写模式到读模式
                    buffer.flip();
                    //把ByteBuffer变成字符串
                    String str = Charset.defaultCharset().decode(buffer).toString();
                    System.out.println(str);
                    if("quit".equals(str)){
                        //如果服务器收到quit，则关闭
                        channel.write(ByteBuffer.wrap("quit".getBytes()));
                        channel.close();
                    }else{
                    String s = str.toUpperCase();

                    //把string转成ByteBuffer
                    buffer = ByteBuffer.wrap(s.getBytes());
                    //发送给客户端
                    channel.write(buffer);
                    }

                }
            }


        }
    }
}
